﻿using System;
using UnityConfiguration.Infrastructure;
using System.Collections.Generic;
using mpuu = Microsoft.Practices.Unity.Utility;
using mpu = Microsoft.Practices.Unity;
using System.Globalization;
using UnityConfiguration.Properties;
using System.Windows.Markup;
using System.Linq;

namespace UnityConfiguration
{
    /// <summary>
    /// A configuration element that represents an array to be resolved.
    /// </summary>
    [ContentProperty("Elements")]
    public class Array : InjectionParameterValue, IValue
    {
        private List<InjectionParameterValue> _Elements = new List<InjectionParameterValue>();

        public IEnumerable<IValue> Elements {
            get { return _Elements.Cast<IValue>(); }
            set { _Elements = value.Cast<InjectionParameterValue>().ToList(); }
        }

        /// <summary>
        /// Return an instance of <see cref="InjectionParameterValue"/> based
        /// on the contents of this element.
        /// </summary>
        /// <param name="targetType">Type of parent parameter. Ignored by this implementation.</param>
        /// <returns>The created InjectionParameterValue, ready to pass to the container config API.</returns>
        /// <seealso cref="ResolvedArrayParameter"/>
        public override mpu.InjectionParameterValue CreateParameterValue(Type targetType) {
            mpuu.Guard.ArgumentNotNull(targetType, "targetType");

            if (!targetType.IsArray) {
                throw new InvalidOperationException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.ParameterTypeIsNotArray,
                        targetType.Name));
            }

            Type elementType = targetType.GetElementType();
            string elementTypeName = elementType.AssemblyQualifiedName;

            object[] elementValues = new object[_Elements.Count];
            for (int i = 0; i < _Elements.Count; i++) {
                elementValues[i]
                    = InjectionParameterValueHelper.CreateParameterValue(
                        elementTypeName,
                        null,
                        _Elements[i],
                        TypeResolver);
            }
            return new mpu.ResolvedArrayParameter(elementType, elementValues);
        }

        internal mpu.InjectionParameterValue CreateParameterValue(string genericParameterName) {
            object[] elementValues = new object[_Elements.Count];
            for (int i = 0; i < _Elements.Count; i++) {
                elementValues[i]
                    = InjectionParameterValueHelper.CreateParameterValue(
                        null,
                        genericParameterName,
                        _Elements[i],
                        TypeResolver);
            }
            return new mpu.GenericResolvedArrayParameter(genericParameterName, elementValues);
        }
    }
}
